<template>
    <transition name="animate__animated " enter-active-class="animate__lightSpeedInLeft animate__fast "
        leave-active-class="animate__fadeOutRight animate__faster">
        <div class="qrCodeInfo forbid-select" @click="close" v-if="modelValue" ref="qrCode">
            <div class="qrCodeBg" @click.stop>
                <div class="title">{{ loginfo.websiteName }}</div>
                <div class="tip">使用小程序扫码登录</div>
                <div class="qrcodeBox">
                    <div v-if="!loginSuccess">
                        <img src="@/assets/image/logo.png" class="qrCodeLogo" alt="logo">
                        <canvas ref="qrcodeCanvas" class="qrcode" id="qrcode" />
                        <div class="expireTime" v-if="expireTime > 0">
                            剩余过期时间<span class="expireSecond"> {{ expireTime }}</span>秒
                        </div>
                        <div class="expireModel" v-if="!expireTime && status !== 0" @click="getQrImg">
                            <div class="expireTime">二维码已过期</div>
                            <div class="expireTip">已过期<br>点击重新获取</div>
                        </div>
                        <div class="expireModel" v-if="status === -1 && expireTime && !loginSuccess">
                            <div class="expireTip">已扫码<br>等待手机确认</div>
                        </div>
                        <div class="expireModel" v-if="status === 0 && !loginSuccess" @click="getQrImg">
                            <div class="expireTip">已取消<br>点击重新获取</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </transition>
    <div class="login-container forbid-select animate__animated animate__fadeIn animate__faster" v-if="modelValue"
        ref="qrCodeModel"></div>
</template>

<script setup>
import { useRequest } from "@usehook"
import ElLoading from '@/components/loading'
import { encryption, broadcastEvent } from '@/utils/tools'
import QRCode from 'qrcode'
import { baseUrl } from "@/utils/request"
import { useMainStore, useUserStore } from "@/pinia"
import { nextTick } from 'vue'

// 定义父组件传参
const props = defineProps({
    modelValue: {
        type: Boolean,
        default: false
    }
})
// 定义父组件事件
const emits = defineEmits(['update:modelValue'])
// 状态管理
const store = useMainStore()
// 登录所需的信息及网站信息所保存的内容
let loginfo = $ref({})
// 发送登录请求的socket对象
let socket = $ref(null)
// 是否登录成功
let loginSuccess = $ref(false)
// 监听网站基础数据
watch(() => store.getWebInfo, (value) => {
    loginfo = value
})

// 关闭登录弹窗
const close = () => {
    emits("update:modelValue", false)
    clearQrInterval()
    socket.close()
}
// 二维码序列
let qrcodeSequence = $ref("")
// 二维码canvas
const qrcodeCanvas = $ref("")
// 二维码过期时间计时器
let interval = $ref(null)
// 二维码状态
let status = $ref(1)
// 二维码过期时间
let expireTime = $ref(0)
// 清除二维码计时器
const clearQrInterval = () => {
    clearInterval(interval)
}
// 请求二维码序列号,生成二维码图片
const getQrImg = () => {
    // 状态重置
    status = 1
    loginSuccess = false
    expireTime = -1
    clearQrInterval()
    const loading = ElLoading.service({ text: "正在生成二维码", target: ".qrcodeBox" })
    // 请求二维码序列号
    useRequest({ url: "/getLoginQrCode", source: encryption("www.qr") }).then((e) => {
        qrcodeSequence = e.data
        // 生成二维码图片
        QRCode.toCanvas(qrcodeCanvas, qrcodeSequence, {
            errorCorrectionLevel: 'H', quality: 1, margin: 0, color: {
                dark: "#008B45FF", light: "#ffffff80"
            }, width: 150, height: 150,
        }, (e) => {
            console.log(e || "二维码加载成功")
        })
        // 初始化socket
        initWebSocket()
        // 获取二维码过期时间
        expireTime = loginfo.expireTime
        // 开始计时,更新二维码过期时间
        interval = setInterval(() => {
            expireTime -= 1
            if (expireTime === 0) {
                const message = JSON.stringify({
                    status: 0,
                    message: "已过期",
                    type: "expired"
                })
                socket.send(message)
                socket.close()
                clearQrInterval()
            } else if (expireTime % 50 === 0) {
                const message = JSON.stringify({
                    status: 0,
                    message: "剩余过期时间:" + expireTime,
                    type: "heart"
                })
                socket.send(message)
            }
        }, 1000)
    }).finally(() => {
        loading.close()
    })
}

const initWebSocket = () => {
    if (typeof (WebSocket) == "undefined") {
        console.log("浏览器不支持WebSocket");
    } else {
        //实现化WebSocket对象，指定要连接的服务器地址与端口  建立连接
        //等同于socket = new WebSocket("ws://localhost:8083/checkcentersys/websocket/20");
        const wsPath = baseUrl.replace(/http/g, "ws") + "/getQrCode/" + qrcodeSequence;
        socket = new WebSocket(wsPath);
        //打开事件
        socket.onopen = function () {
            //socket.send("这是来自客户端的消息" + location.href + new Date());
        };
        //获得消息事件
        socket.onmessage = function (msg) {
            const result = JSON.parse(msg.data);
            if (result.status) {
                if (!result.data && result.message === '-1') {
                    status = -1
                } else if (!result.data && result.message === '0') {
                    status = 0
                    socket.close();
                    clearQrInterval()
                } else if (result.data && !result.message) {
                    loginSuccess = true
                    const loading = ElLoading.service({ text: "正在登录", target: ".qrcodeBox" })
                    useUserStore().login(result.data)
                    setTimeout(() => {
                        socket.close()
                        clearQrInterval()
                        loading.close()
                        close()
                        broadcastEvent("login", true)
                    }, 20);
                } else {
                    //如果过期了，关闭连接、重置连接、刷新二维码
                    socket.close();
                    clearQrInterval()
                    getQrImg();
                }
            } else {
                socket.close();
                clearQrInterval()
                getQrImg();
            }
        };
        //关闭事件
        socket.onclose = function () {
            clearQrInterval()
            expireTime = 0
        };
        //发生了错误事件
        socket.onerror = function (e) {
            clearQrInterval()
            expireTime = 0
            //此时可以尝试刷新页面
        }
    }
}

// 指向login,插入到body中
const qrCodeModel = $ref(null)
const qrCode = $ref(null)

watch(() => props.modelValue, (value) => {
    if (value) {
        nextTick(() => {
            document.body.append(qrCodeModel);
            document.body.append(qrCode);
            getQrImg()
        })

    }
}, { immediate: true })

const saveUserInfo = (data) => {

}

</script>

<style scoped>
.login-container,
.qrCodeInfo {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
}

.login-container {
    background: rgba(0, 0, 0, .5);
    z-index: 998;

}

.qrCodeInfo {
    z-index: 999;
}

:deep(.qrCodeInfo) {
    width: 100%;
    height: 100%;
    position: relative;
}

:deep(.qrCodeBg) {
    position: relative;
    top: calc(30% - 50px);
    left: calc(50% - 200px);
    width: 450px;
    height: 250px;
    background: rgb(237 226 198);
    border-radius: var(--border-radius);
}

:deep(.qrcode) {
    padding: 10px 10px 0 10px
}

:deep(.qrcodeBox) {
    width: 170px;
    height: 180px;
    position: absolute;
    bottom: 10px;
    right: 20px;
    background: #fff;
}

:deep(.expireTime) {
    font-size: 14px;
    color: #ff3c3c;
    height: 18px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
}

:deep(.expireModel) {
    height: 100%;
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background: rgba(255, 255, 255, .9)
}

:deep(.expireSecond) {
    width: 50px;
    font-size: 20px;
    text-align: center;
    letter-spacing: 2px
}

:deep(.title) {
    text-align: center;
    font-size: 35px;
    padding: 12px 0;
    color: var(--font-color)
}

:deep(.tip) {
    font-size: 20px;
    color: var(--font-color);
    height: 160px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 255px;
}

:deep(.expireTip) {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: calc(100% - 19px);
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    line-height: 30px;
    font-size: 20px;
}

:deep(.el-loading-spinner .el-loading-text) {
    color: rgba(65, 110, 110, .8);
}

:deep(.qrCodeLogo) {
    width: 40px;
    height: 40px;
    position: absolute;
    z-index: 1;
    left: 65px;
    top: 65px;
    pointer-events: none;
}

#qrcode {
    position: relative;

    &::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        background: linear-gradient(45deg, #673ab7, #ff5722);
        mix-blend-mode: lighten;
    }
}
</style>